package com.zx.idc.backend.gui.api.ws.services.handler.template;

import com.zx.idc.backend.gui.api.commom.base.BaseIDCCommandService;
import com.zx.idc.backend.gui.api.commom.entity.CommandModel;
import com.zx.idc.backend.gui.api.commom.factory.ReturnFactory;
import com.zx.idc.common.spring.SpringBeanUtil;
import com.zx.idc.ds.ins.entity.InsIdcCommandLog;
import com.zx.idc.ds.ins.factory.InsIdcCommandLogFactory;
import com.zx.idc.ds.ins.service.IInsIdcCommandLogService;
import com.zx.idc.ds.ins.service.impl.InsIdcCommandLogServiceImpl;
import org.apache.commons.lang3.StringUtils;
import static com.zx.idc.common.attributes.InterfaceParamConfiguration.*;
import static com.zx.idc.common.attributes.SystemAttributes.WEB_SERVICE_VERSION;

/**
 * Created by hasee on 2019/2/21.
 * IDC接收管理指令模板
 */
public abstract class IdcCommandReceiveTemplate extends BaseIDCCommandService {


    /**
     * IDC指令接收模板
     *
     * @param commandModel
     * @return
     */
    public final String receiveCommandTemplate(CommandModel commandModel) {
        try {
            //获取唯一序号，判断是否重复发送指令
            Long commandSequence = commandModel.getCommandSequence();
            IInsIdcCommandLogService iInsIdcCommandLogService = SpringBeanUtil.getBean(InsIdcCommandLogServiceImpl.class);
            boolean exists = iInsIdcCommandLogService.exists(new InsIdcCommandLog().setCommandSequence(commandSequence));
            //存在直接返回
            if (exists) {
                LOG.debug("指令重复发送，调用结束!");
                return ReturnFactory.getOKReturn("指令已经处理了，请别在重复发送!");
            } else {
                //新增记录
                iInsIdcCommandLogService.insert(InsIdcCommandLogFactory.entity().setCommandSequence(commandSequence));
            }
            //验证版本兼容
            LOG.debug("验证版本兼容性");
            String version = getConfig(WEB_SERVICE_VERSION);
            if (!version.equals(commandModel.getCommandVersion())) {
                LOG.debug("版本不兼容,返回最新版本,调用结束");
                return ReturnFactory.getVersionCompatibilityReturn(version);
            }
            LOG.debug("验证版本兼容成功");
            String userPassword = getVal(USER_PASSWORD);
            LOG.debug("用户口令:{}", userPassword);
            String encryptionKey = getVal(ENCRYPTION_KEY);
            LOG.debug("加密密钥:{}", encryptionKey);
            String authenticationKey = getVal(AUTHENTICATION_KEY);
            LOG.debug("认证消息秘钥:{}", authenticationKey);
            int digestType = Integer.parseInt(getVal(HASH_ALGORITHM));
            LOG.debug("签名算法类型:{}", digestType);
            int compressionFormatNum = Integer.parseInt(getVal(COMPRESSION_FORMAT));
            LOG.debug("压缩算法类型:{}", compressionFormatNum);
            int encryptionAlgorithmNum = Integer.parseInt(getVal(ENCRYPTION_ALGORITHM));
            LOG.debug("加密算法类型:{}", encryptionAlgorithmNum);

            //验证
            LOG.debug("身份认证");
            if (authentication(digestType, commandModel.getRandVal(), userPassword, commandModel.getPwdHash())) {
                LOG.debug("身份认证成功");
                //通过验证
                //指令文件处理过程
                //1.解密指令
                LOG.debug("指令文件处理:");
                LOG.debug("1.对指令内容进行Base64解码+解密");
                String text = commandModel.getCommand();
                byte[] data = decodeAsBytes(encryptionAlgorithmNum, text, encryptionKey, getVal(ASE_OFFSET));
                LOG.debug("解密后的字节数组:{}", data);
                LOG.debug("2.commandHash 核验");
                if (hashVerify(digestType, data, commandModel.getCommandHash(), authenticationKey)) {
                    //解压
                    LOG.debug("3.解压指令信息");
                    String commandXML = deCmp(compressionFormatNum, data);
                    LOG.debug("解压后的指令信息:{}", commandXML);
                    if (StringUtils.isNotEmpty(commandXML)) {
                        //获取类型的指令实体
                        //构建数据对象
                        LOG.debug("获取指令信息后调用相应的服务处理,指令类型:{}", commandModel.getCommandType());
                        return service(commandModel.getCommandType(), commandXML, commandModel);
                    }
                    LOG.debug("解压失败,调用结束");
                    return ReturnFactory.getDecompressionFailedReturn("解压失败");
                }
                LOG.debug("认证不通过,解密失败,调用结束");
                return ReturnFactory.getDecryptionFailedReturn("解密失败");
            }
            LOG.debug("身份认证失败,调用结束");
            return ReturnFactory.getOtherExceptionReturn("认证不通过");
        }catch(Exception e){
            LOG.error(e.getMessage(), e);
            return ReturnFactory.getOtherExceptionReturn("处理失败");
        }
    }

    //获取类型的指令实体
    //构建数据对象
    public abstract String service(int type, String data, CommandModel commandModel);
}
